#include <errno.h>
#include <string.h>
#include "sint.h"
#include "ts2006.h"
extern int cima;
extern int tabla_simbolos[MAX];
extern tipo_nombre_tabla lista_nombre_tabla[MAX];
extern char nombre_tmp[MAX_NOMBRE];
unsigned short int push_hechos;

short int emite_tabla (int ts, int ts_anterior){
  int desp_actual   = 0;
  int desp_anterior = 0;
  FILE * ftabla     = NULL;
  memset  (nombre_tmp, 0, MAX_NOMBRE * sizeof(char));
  strncat (nombre_tmp, lista_nombre_tabla[cima], MAX_NOMBRE);
  strncat (nombre_tmp, ".tabla", 6);
  
  desp_actual =
    consultar_valor_atributo_entero(ts,
                                    "desplazamiento_maximo",
                                    "valor");

  desp_anterior =
    consultar_valor_atributo_entero(ts_anterior,
                                    "desplazamiento_maximo",
                                    "valor");
  //  arreglo entre direcciones y posiciones
  desp_actual   = desp_actual   / 4;
  desp_anterior = desp_anterior / 4;
  
  if((ftabla = fopen(nombre_tmp, "w")) == NULL) {
    fprintf(stderr,
            "Error abriendo el fichero de la tabla %s\n",
            nombre_tmp);
    exit(-1);
  }

  if (ts_anterior != 0) {
    fprintf(ftabla, "ADD  #1,     .SP   ;  .A  = N.direccion\n");
    fprintf(ftabla, "MOVE  .A,    .R9   ;  .R9 = N.direccion\n");
    fprintf(ftabla, "MOVE [.R9],  .R8   ;  .R8 = N\n");
/*     fprintf(ftabla, "ADD  #1,     .R8   ;  .A  = N + 1\n"); */
/*     fprintf(ftabla, "MOVE  .A,    .R7   ;  .R7 = N + 1\n"); */
    //  ((desp - 1) - N + 3) * 2
    fprintf(ftabla, "SUB  #%.3d,  #1    ;  .A  = desp_actual -1\n",
            desp_actual);
    fprintf(ftabla, "SUB   .A,    .R8   ;  .A  = (desp_actual - 1) - N\n");
    fprintf(ftabla, 
            "SUB   .A,    #3    ;  .A  = ((desp_actual - 1) - N) - 3\n");

    fprintf(ftabla, "MOVE  .A,    .R6   ;  .R6 = nuevos_eltos\n");
    fprintf(ftabla,
            "SUB   .SP,   .R6   ;  .A  = casi_nuevo_SP + nuevos_eltos\n");
    fprintf(ftabla, "SUB   .A,    .R6   ;  .A  = casi_nuevo_SP\n");
    fprintf(ftabla, "SUB   .A,    #1    ;  .A  = nuevo_SP\n");
    fprintf(ftabla, "MOVE  .A,    .SP   ;  .SP = nuevo_SP\n");

    fprintf(ftabla, "ADD   #%.3d, .R6 ;  .A  =  desp_actual + nuevos_eltos\n",
            desp_actual);
    fprintf(ftabla, "SUB   .A,    #1    ;  .A  = desp_actual + nuevos_eltos - 1\n");
    fprintf(ftabla, "MOVE  .A,    .R1   ;  .R1 = 2*desp_actual\n");
    fprintf(ftabla, "ADD   .SP,   #1    ;  .A  = n_pop.direccion\n");
    fprintf(ftabla, "MOVE  .A,    .R2   ;  .R4 = n_pop.direccion\n");
    fprintf(ftabla, "MOVE  .R1,  [.R2]  ;  guardo el n_pop\n");

    fprintf(ftabla, "ADD   .R9,   .R8    ;  .A = elto_a_copiar.direccion\n");
    fprintf(ftabla, "MOVE  .A,    .R5   ;  .R5 = elto_a_copiar.direccion\n");
    fprintf(ftabla, "ADD   #3,    .SP   ;  .A  = elto_copiado.direccion\n");
    fprintf(ftabla, "MOVE  .A,    .R4   ;  .R4 = elto_copiado.direccion\n");
    fprintf(ftabla, "MOVE  .R8,   .R3   ;  .R3 = n_eltos_a_copiar\n");
    fprintf(ftabla, "CMP   .R3,   #0    ;  .A   = CMP .R3 #0\n");
    fprintf(ftabla, "BZ    $10          ;  if copiar_eltos==0 goto poner_0s\n");
    fprintf(ftabla,
            "MOVE [.R5], [.R4]  ;  elto_a_copiar.dir => elto_copiado.dir\n");
    fprintf(ftabla, "DEC   .R3          ;  n_eltos_a_copiar--\n");
    fprintf(ftabla, "INC   .R4          ;  elto_a_copiar.dir ++\n");
    fprintf(ftabla, "DEC   .R5          ;  elto_copiado.dir ++\n");
    fprintf(ftabla, "BR    $-15         ;  goto if copiar_eltos==0\n");


    fprintf(ftabla, "ADD   .R4,   .R6   ;  .A  = elto_a_copiar\n");
    fprintf(ftabla, "MOVE  .A,    .R5   ;  .R5  = elto_a_copiar\n");
    fprintf(ftabla, "MOVE  .R6,   .R3   ;  .R3 = n_eltos_a_copiar\n");
    fprintf(ftabla, "CMP   .R3,   #0    ;  .A   = CMP .R3 #0\n");
    fprintf(ftabla, "BZ    $10          ;  if copiar_eltos==0 goto poner_0s\n");
    fprintf(ftabla,
            "MOVE  .R5,  [.R4]  ;  elto_a_copiar => elto_copiado.dir\n");
    fprintf(ftabla, "DEC   .R3          ;  n_eltos_a_copiar--\n");
    fprintf(ftabla, "INC   .R4          ;  elto_a_copiar.dir ++\n");
    fprintf(ftabla, "INC   .R5          ;  elto_copiado.dir ++\n");
    fprintf(ftabla, "BR    $-15         ;  goto if copiar_eltos==0\n");


    fprintf(ftabla, "MOVE  .R6,   .R2   ;  .R2 = nuevos_eltos\n");
    fprintf(ftabla, "MOVE  .R4,   .R1   ;  .R1 = elto_poner_0.direccion\n");
    fprintf(ftabla, "CMP   .R2,   #0    ;  .A   = CMP .R3 #0\n");
    fprintf(ftabla, "BZ    $9           ;  if copiar_eltos==0 goto poner_0s\n");
    fprintf(ftabla,
            "MOVE #0,    [.R1]  ;  elto_a_copiar.dir => elto_copiado.dir\n");
    fprintf(ftabla, "DEC   .R2          ;  n_eltos_a_copiar--\n");
    fprintf(ftabla, "INC   .R1          ;  elto_a_copiar.dir ++\n");
    fprintf(ftabla, "BR    $-14         ;  goto if copiar_eltos==0\n");

    fprintf(ftabla, "MOVE  #%.3d,  .R9   ;  .R9  = desplazamiento_PA\n",
            desp_actual);
    fprintf(ftabla, "ADD   .SP,   #2    ;  .A  = .SP + \n");
    fprintf(ftabla, "MOVE  .A,    .R8   ;  .R8 = .SP + 2\n");
    fprintf(ftabla, "ADD   .R9,   .R8   ;  .A  = casi PA_antiguo.dir\n");
    fprintf(ftabla, "ADD   .A,    .R6   ;  .A  = PA_antiguo.dir + 1\n");
    fprintf(ftabla, "SUB   .A,    #1    ;  .A  = PA_antiguo.dir\n");
    fprintf(ftabla, "MOVE  .A,    .R7   ;  .R7 = PA_antiguo.dir\n");
    // NUEVO
    fprintf(ftabla, "SUB   #%.3d, /CIMA ;  es_cima==ts\n", ts);
    fprintf(ftabla, "CMP   .A,    #0    ;  cima > ts\n");
    fprintf(ftabla, "BNZ   $10          ;  cima > ts\n");
    fprintf(ftabla, "MOVE  [.R7], .R7   ;  .R7 = [PA_antiguo.dir]\n");
    fprintf(ftabla, "MOVE  /NCIMA, .R5  ;  .R5 = /NCIMA\n");
    fprintf(ftabla, "INC   .R5          ;  .R5++\n");
    fprintf(ftabla, "MOVE  .R5,   /NCIMA ;  /NCIMA = .R5\n");
    fprintf(ftabla, "MOVE   #%.3d, /CIMA ;  CIMA = ts == %.3d\n", ts, ts);
    // NUEVO
    fprintf(ftabla, "MOVE  .R7,  [.R8]  ;  PA_nuevo = PA_antiguo.dir\n");
    fprintf(ftabla, "                   ;  para comodidad de debug todo a 0\n");
    fprintf(ftabla, "MOVE  #0,    .A    ;  .A  = 0\n");
    fprintf(ftabla, "MOVE  #0,    .R0   ;  .R0 = 0\n");
    fprintf(ftabla, "MOVE  #0,    .R1   ;  .R1 = 0\n");
    fprintf(ftabla, "MOVE  #0,    .R2   ;  .R2 = 0\n");
    fprintf(ftabla, "MOVE  #0,    .R3   ;  .R3 = 0\n");
    fprintf(ftabla, "MOVE  #0,    .R4   ;  .R4 = 0\n");
    fprintf(ftabla, "MOVE  #0,    .R5   ;  .R5 = 0\n");
    fprintf(ftabla, "MOVE  #0,    .R6   ;  .R6 = 0\n");
    fprintf(ftabla, "MOVE  #0,    .R7   ;  .R7 = 0\n");
    fprintf(ftabla, "MOVE  #0,    .R8   ;  .R8 = 0\n");
    fprintf(ftabla, "MOVE  #0,    .R9   ;  .R9 = 0\n");
    fprintf(ftabla, "CALL /%s           ;  CALL /%s\n",
            lista_nombre_tabla[cima], lista_nombre_tabla[cima]);  // retorno?
    push_hechos = 0;
  } else {
    fprintf(ftabla, "MOVE #32767,  .SP  ;  .SP = ultima_posicion_16_bits\n");
    fprintf(ftabla, "MOVE #%.3d,    .R1  ;  .R1 = desp_actual\n",
            desp_actual);
    fprintf(ftabla, "SUB  #%.3d,   #4    ;  .A  = posiciones_a_poner_a_0\n",
            desp_actual);
    fprintf(ftabla,
            "MOVE  .A,     .R9  ;  .R9 = posiciones_a_poner_a_0\n");
    fprintf(ftabla, "MOVE  .R9,    .R8  ;  .R8 = posiciones_a_poner_a_0\n");
    fprintf(ftabla, "CMP   .R8,   #0    ;  .A  = CMP .R8 #0\n");
    fprintf(ftabla,
            "BZ   $9            ;  if palabras_a_0 == 0 goto fin_a_0\n");
    fprintf(ftabla,
            "PUSH #0            ;  PUSH 0\n");
    fprintf(ftabla,
            "SUB   .R8,   #1    ;  .A = posiciones_a_poner_a_0 - 1\n");
    fprintf(ftabla,
            "MOVE  .A,     .R8  ;  .A = posiciones_a_poner_a_0 - 1\n");
    fprintf(ftabla, "BR   $-14          ;  goto es_palabras_a_0\n");
    fprintf(ftabla,
            "MOVE  .R9,    .R7  ;  .R7 = constant posiciones_a_poner_a_0\n");
    fprintf(ftabla,
            "MOVE  .R7,    .R6  ;  .R6 = contador posiciones_a_poner_a_0\n");
    fprintf(ftabla, "CMP   .R6,   #0    ;  .A  = CMP .R8 #0\n");
    fprintf(ftabla,
            "BZ   $13           ;  if palabras_a_0 == 0 goto fin_a_0\n");
    fprintf(ftabla,
            "ADD   .SP,    .R7  ;  .A  = variable.direccion\n");
    fprintf(ftabla,
            "MOVE  .A,     .R5  ;  .R5 = variable.direccion\n");
    fprintf(ftabla,
            "PUSH  .R5          ;  PUSH .R5\n");
    fprintf(ftabla,
            "SUB   .R6,   #1    ;  .A  = posiciones_a_poner_a_0 - 1\n");
    fprintf(ftabla,
            "MOVE  .A,     .R6  ;  .A  = posiciones_a_poner_a_0 - 1\n");
    fprintf(ftabla, "BR   $-18           ;  goto es_palabras_a_0\n");
    fprintf(ftabla,
            "PUSH #0           ;  PUSH 0, PA es 0\n");
    fprintf(ftabla,"MOVE  #%.3d,    /CIMA  ; /CIMA = #%.3d\n",ts,ts);
    fprintf(ftabla,"MOVE  #1,    /NCIMA ;  .R5 = /NCIMA\n");
    fprintf(ftabla,
            "ADD   .R9,    .R9  ;  .R9 = 2*posiciones_a_poner_a_0\n");
    fprintf(ftabla,
            "ADD   .A,    #3    ;  .A  = 2*posiciones_a_poner_a_0 + 3\n");
    fprintf(ftabla,
            "MOVE  .A,     .R1  ;  .R1 = 2*posiciones_a_poner_a_0 + 3\n");
    fprintf(ftabla,
            "PUSH  .R1          ;  PUSH (2*posiciones_a_poner_a_0 + 3)\n");
    fprintf(ftabla,
            "MOVE  #TOTALFIN, .R2  ;  .R2 = 2*posiciones_a_poner_a_0 + 3\n");
    fprintf(ftabla,
            "PUSH  .R2          ;  PUSH (2*posiciones_a_poner_a_0 + 3)\n");
    fprintf(ftabla, "MOVE  #0,    .A    ;  .A  = 0\n");
    fprintf(ftabla, "MOVE  #0,    .R0   ;  .R0 = 0\n");
    fprintf(ftabla, "MOVE  #0,    .R1   ;  .R1 = 0\n");
    fprintf(ftabla, "MOVE  #0,    .R2   ;  .R2 = 0\n");
    fprintf(ftabla, "MOVE  #0,    .R3   ;  .R3 = 0\n");
    fprintf(ftabla, "MOVE  #0,    .R4   ;  .R4 = 0\n");
    fprintf(ftabla, "MOVE  #0,    .R5   ;  .R5 = 0\n");
    fprintf(ftabla, "MOVE  #0,    .R6   ;  .R6 = 0\n");
    fprintf(ftabla, "MOVE  #0,    .R7   ;  .R7 = 0\n");
    fprintf(ftabla, "MOVE  #0,    .R8   ;  .R8 = 0\n");
    fprintf(ftabla, "MOVE  #0,    .R9   ;  .R9 = 0\n");
  }
  fclose(ftabla);
  return (0);
}
